/**
 *  @file  UdpStream.h version 1.0 2007-11-20 
 *  @brief Define class FileOutput.
 *  Copyright (c) 2007 by @author <abitfree@gmail.com>
 */

#ifndef __VS_FILE_OUTPUT_H__
#define __VS_FILE_OUTPUT_H__

#include "vsLogOutput.h"

namespace vs {
namespace log {

/**
 * @brief The file log output class, it's the root class for file outputs. 
 *
 * This class can only log into one file. The base class for FixedSizeFileOutput, TimeRollingOutput.
*/
class FileOutput : public LogOutput
{
public:
	/// The max length of a file name, content the whole path.
	enum { MAX_FILE_NAME = 512 };

	/// The constructor.
	FileOutput(const char *pszFileHeader = 0, const char *pszDirectory = 0);

	/// The virtual destructor.
	virtual ~FileOutput();
	
	/// Write a log message, it is usually called by the Logger class objects.
	virtual int Write(const char *pszMsg, int nSize, struct tm *pWriteTime);

	/// Flush log messages to file.
	virtual void Flush();

protected:
	/// Get the file name of the current object.
	virtual const char* GetFileName();
    
	/// Set the log file header.
	void SetLogFileNameHeader(const char *pszFileHeader);

	/// Get the log file header.
	const char* GetLogFileNameHeader();

	/// Set the log file directory.
	void SetLogDirectory(const char *pszDirectory);

	/// Get the log file directory.
	const char* GetLogDirectory();

	/// Switch a file, if needed.
	virtual void SwitchFile(int nWriteSize, struct tm *pWriteTime);

	/// The Open() method is aim to setting up the target objects for logging messages.
	virtual bool Open();
	
	/// Close the log output.
	virtual void Close();

	// File handle.
	FILE *m_File;

	// Log file name header.
	char m_LogFileNameHeader[MAX_FILE_NAME];

	// Log file directory.
	char m_LogDirectory[MAX_FILE_NAME];
};


#define INLINE inline

INLINE
FileOutput::FileOutput(const char *pszFileHeader, const char *pszDirectory)
	: m_File(0)
{
	SetLogFileNameHeader(pszFileHeader);
	SetLogDirectory(pszDirectory);
	Open();
}

INLINE
FileOutput::~FileOutput()
{
	Close();
}

INLINE
int FileOutput::Write(const char *pszMsg, int nSize, struct tm *pWriteTime)
{
	return fwrite(pszMsg, 1, nSize, m_File);
}

INLINE
void FileOutput::Flush()
{
	fflush(m_File);
}

INLINE
const char* FileOutput::GetFileName()
{
    time_t tNow;
	tNow = time(0);
	struct tm *pTm = localtime(&tNow);
	static char file_name[MAX_FILE_NAME];
    _snprintf(file_name, MAX_FILE_NAME, "%s\\%s_%04d%02d%02d%02d%02d%02d.log", GetLogDirectory(), GetLogFileNameHeader(), pTm->tm_year+1900, 
                        pTm->tm_mon+1, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
	return file_name;
}

INLINE
void FileOutput::SetLogFileNameHeader(const char *pszFileHeader)
{
	// default to current directory
	if ((pszFileHeader == NULL) || pszFileHeader[0] == 0)
	{
		strcpy(m_LogFileNameHeader, "FileOutput");
	}
	else
	{
		strncpy(m_LogFileNameHeader, pszFileHeader, MAX_FILE_NAME);
	}
}

INLINE
const char* FileOutput::GetLogFileNameHeader()
{
	return m_LogFileNameHeader;
}

INLINE
void FileOutput::SetLogDirectory(const char *pszDirectory)
{
	// default to current directory
	if ((pszDirectory == NULL) || pszDirectory[0] == 0)
	{
		strcpy(m_LogDirectory, ".");
	}
	else
	{
		strncpy(m_LogDirectory, pszDirectory, MAX_FILE_NAME);
	}
}

INLINE
const char* FileOutput::GetLogDirectory()
{
	return m_LogDirectory;
}

INLINE
void FileOutput::SwitchFile(int nWriteSize, struct tm *pWriteTime)
{
}

INLINE
bool FileOutput::Open()
{
	if (m_File != NULL)
	{
		fclose(m_File);
	}
	const char* file_path = GetFileName();
	m_File = fopen(file_path, "wb");
	return m_bValid = (m_File != NULL);
}

INLINE
void FileOutput::Close()
{
	if (m_File != NULL)
	{
		fclose(m_File);
		m_bValid = false;
	}
}

} // namespace log
} // namespace vs

#endif // __VS_FILE_OUTPUT_H__
